#include "BulletState.h"

/*
================================
BulletState::Instance

Singleton pattern.
================================
*/
State* BulletState::Instance()
{
	static BulletState the_BulletState;
	return &the_BulletState;
}

/*
================================
BulletState::BulletState
================================
*/
BulletState::BulletState()
{
	
}

// globals
btCollisionShape* groundShape;
btCollisionShape* fallShape;

btDefaultMotionState* groundMotionState;
btRigidBody* groundRigidBody;

btDefaultMotionState* fallMotionState;
btRigidBody* fallRigidBody;

/*
================================
BulletState::init
================================
*/
void BulletState::init( Engine* game )
{
	frames_elapsed = 0;

	// Build the broadphase
	broadphase = new btDbvtBroadphase();
	// Set up the collision configuration and dispatcher
	collisionConfiguration = new btDefaultCollisionConfiguration();
	dispatcher = new btCollisionDispatcher(collisionConfiguration);
	// The actual physics solver
	solver = new btSequentialImpulseConstraintSolver;
	// The world.
	dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
	dynamicsWorld->setGravity(btVector3(0,0,-10));


	// For pedantic purposes, the gS was made at 1, and the gMS was shifted back by -1.

	// Collision shapes
	groundShape = new btStaticPlaneShape(btVector3(0,0,1),1);
	fallShape = new btSphereShape(1);
	// Rigid bodies
	// Ground
	groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,0,-1)));
	btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
	groundRigidBody = new btRigidBody(groundRigidBodyCI);
	dynamicsWorld->addRigidBody(groundRigidBody);
	// Ball
	fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,0,50)));
	btScalar mass = 1;
	btVector3 fallInertia(0,0,0);
	fallShape->calculateLocalInertia(mass,fallInertia);
	btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
	fallRigidBody = new btRigidBody(fallRigidBodyCI);
	dynamicsWorld->addRigidBody(fallRigidBody);
}

/*
================================
BulletState::cleanup
================================
*/
void BulletState::cleanup( Engine* game )
{
	dynamicsWorld->removeRigidBody(fallRigidBody);
	delete fallRigidBody->getMotionState();
	delete fallRigidBody;

	dynamicsWorld->removeRigidBody(groundRigidBody);
	delete groundRigidBody->getMotionState();
	delete groundRigidBody;

	delete fallShape;
	delete groundShape;

	// Clean up behind ourselves like good little programmers
	delete dynamicsWorld;
	delete solver;
	delete dispatcher;
	delete collisionConfiguration;
	delete broadphase;
}

/*
================================
BulletState::input
================================
*/
void BulletState::input( Engine* game )
{
	
}

/*
================================
BulletState::update
================================
*/
void BulletState::update( Engine* game )
{
	frames_elapsed++;

	dynamicsWorld->stepSimulation( 1/60.f, 10 );
}

/*
================================
BulletState::draw
================================
*/
void BulletState::draw( Engine* game )
{
	
}

/*
================================
BulletState::setCaption
================================
*/
void BulletState::setCaption( std::ostringstream& buffer )
{
	buffer << " || BulletState:";
	buffer << " " << frames_elapsed << " frames elapsed";

	btTransform trans;
	fallRigidBody->getMotionState()->getWorldTransform( trans );
	buffer << " (" << trans.getOrigin().getX()
		<< ", " << trans.getOrigin().getY()
		<< ", " << trans.getOrigin().getZ() << ")";
}

